﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace SPPatchServiceUI
{
    /// <summary>
    /// Provides managed access to the SharePoint Patch Service API
    /// </summary>
    public static class PatchServiceAPI
    {
        /// <summary>
        /// </summary>
        /// <remarks>
        /// probably won't actually be necessary... but leaving it until such time that it's confirmed
        /// </remarks>
        public enum Products
        {
            [Description("SharePoint Foundation 2010")]
            SPF2010,

            [Description("")]
            SSE2010,

            [Description("SharePoint Server 2010")]
            SPS2010,

            [Description("")]
            SS2010,

            [Description("FAST Search Server 2010")]
            FAST2010,

            [Description("Project Server 2010")]
            PS2010,

            [Description("Office Web Apps 2010")]
            OWA2010,


            [Description("SharePoint Foundation 2013")]
            SPF2013,

            [Description("SharePoint Server 2013")]
            SPS2013,

            [Description("Project Server 2013")]
            PS2013,

            [Description("Office Web Apps 2013")]
            OWA2013
        } // enum Products

        public struct KnownIssue
        {
            //public int ID { get; set; }
            public string KBNumber { get; set; }
            public string Title { get; set; }
            public string Url { get; set; }

            public bool IsResolved { get; set; }
            public string KBResolved { get; set; }
        }
        public struct PatchURL
        {
            public int ID { get; set; }
            public string KBNumber { get; set; }
            public string URL1 { get; set; }
            public string URL2 { get; set; }
            public string URL3 { get; set; }
        }
        public struct Update
        {
            //public int ID { get; set; }
            public string Title { get; set; }
            public string KBNumber { get; set; }
            public string KBURL { get; set; }
            public string BuildNumber { get; set; }
            //public string Product { get; set; }
            public string RequiredLevel { get; set; }
            //public string PatchType { get; set; }
            //public Products ProductInfo { get; set; }
            //public IEnumerable<KnownIssue> KnownIssues { get; set; }
            //public IEnumerable<PatchURL> PatchURLs { get; set; }

            public string PatchURL1 { get; set; }
            public string PatchURL2 { get; set; }
            public string PatchURL3 { get; set; }
        }

        public static IEnumerable<Update> GetUpdates()
        {
            return GetUpdates(Microsoft.SharePoint.Administration.SPFarm.Local.BuildVersion.ToString());
        }
        public static IEnumerable<Update> GetUpdates(string Version)
        {
            var SPPatchServiceAPI_URL = String.Format("http://sharepointpatches.azurewebsites.net/api/Articles/{0}", Version);
            var root = GetData(SPPatchServiceAPI_URL);

            return root.Elements("item")
                       .Select(i => {
                           return new Update()
                           {
                               Title = i.Element("Title").Value,
                               KBNumber = i.Element("KBNumb").Value,
                               KBURL = i.Element("KBUrl").Value,
                               BuildNumber = i.Element("BuildNumber").Value,
                               RequiredLevel = i.Element("RequiredLevel").Value,
                               
                               //KnownIssues = i.Element("").Value,
                               //PatchURLs = new List<PatchURL>()
                               //{
                               //    new PatchURL()
                               //    {
                               //        URL1 = i.Element("PatchUrl1").Value,
                               //        URL2 = i.Element("PatchUrl2").Value,
                               //        URL3 = i.Element("PatchUrl3").Value
                               //    }
                               //},
                               PatchURL1 = i.Element("PatchUrl1").Value,
                               PatchURL2 = i.Element("PatchUrl2").Value,
                               PatchURL3 = i.Element("PatchUrl3").Value,

                           };
                       });
        }

        public static IEnumerable<KnownIssue> GetKnownIssues()
        {
            return GetKnownIssues(Microsoft.SharePoint.Administration.SPFarm.Local.BuildVersion.ToString());
        }
        public static IEnumerable<KnownIssue> GetKnownIssues(string Version)
        {
            var SPPatchServiceAPI_URL = String.Format("http://sharepointpatches.azurewebsites.net/api/KnownIssues"); ///{0}", Version);
            var root = GetData(SPPatchServiceAPI_URL);

            return root.Elements("item")
                       .Select(i =>
                       {
                           return new KnownIssue()
                           {
                               Title = i.Element("IssueTitle").Value,
                               KBNumber = i.Element("KBNumb").Value,

                               Url = i.Element("IssueUrl").Value,
                               IsResolved = Boolean.Parse(i.Element("IsResolved").Value),
                               KBResolved = i.Element("KBResolved").Value,

                           };
                       });
        }


        /// <summary>
        /// handles the actual API webrequest (using proxy where appropriate), and conversion from JSON to XElement using native methods.
        /// </summary>
        /// <remarks>
        /// Sure, other packages may be faster at JSON deserialization, but for the sake of isolation, I prefer to limit the number of assembly references.
        /// </remarks>
        private static System.Xml.Linq.XElement GetData(string url)
        {

            var webReq = System.Net.HttpWebRequest.Create(url);
            webReq.Proxy = new System.Net.WebProxy(webReq.Proxy.GetProxy(webReq.RequestUri)) { UseDefaultCredentials = true };
            var webResp = webReq.GetResponse();

            var jsonReader = System.Runtime.Serialization.Json.JsonReaderWriterFactory.CreateJsonReader(webResp.GetResponseStream(), new System.Xml.XmlDictionaryReaderQuotas());
            var root = System.Xml.Linq.XElement.Load(jsonReader);
            return root;
        }

    } // class
} // namespace